package com.eugenes.design;

import com.eugenes.collections.MyArrayList;
import com.eugenes.collections.MyList;
import com.eugenes.design.cardvalidator.CardValidator;
import com.eugenes.util.Observer;
import java.util.EnumMap;
import java.util.HashSet;
import java.util.Set;

public class SkiPassSystem implements Observer<SkiPassEvent> {

    Set<Card> blockedCards;
    private SkiPassCardFactory factory;
    private CardValidator validator;

    MyList<SkiPassEvent> events;
    EnumMap<SkiPassEvent.PassVerdict, Integer> overallCounts;

    public SkiPassSystem() {
        blockedCards = new HashSet<>();
        events = new MyArrayList<>();
        overallCounts = new EnumMap<>(SkiPassEvent.PassVerdict.class);
    }

    public SkiPassCardFactory getCardFactory() {
        if (factory == null) {
            factory = getNewSkiPassCardFactory();
        }
        return factory;
    }

    public Checkpoint getNewCheckpoint() {
        return new SkiPassCheckpoint(this);
    }

    public boolean blockCard(Card card) {
        return blockedCards.add(card);
    }

    public boolean unblockCard(Card card) {
        return blockedCards.remove(card);
    }

    public int getOverallStats(SkiPassEvent.PassVerdict verdict) {
        Integer count = overallCounts.get(verdict);
        return count == null ? 0 : count;
    }

    @Override
    public void handleEvent(SkiPassEvent event) {
        Integer count = overallCounts.get(event.verdict);
        if (count == null) {
            count = 0;
        }
        ++count;

        overallCounts.put(event.verdict, count);

        // SkiPassEvent is immutable object.
        events.add(event);
    }

    protected CardValidator getNewSystemCardValidator() {
        return new SystemCardValidator();
    }

    CardValidator getSystemCardValidator() {
        if (validator == null) {
            validator = getNewSystemCardValidator();
        }
        return validator;
    }

    protected SkiPassCardFactory getNewSkiPassCardFactory() {
        return new SkiPassCardFactory(this);
    }

    class SystemCardValidator implements CardValidator {

        @Override
        public boolean validate(Card card) {
            return (blockedCards.contains(card) == false);
        }

        @Override
        public void cardIsUsed(Card card) {
            // nothing to do here...
        }
    }
}
